package com.zzh.socketlibrary.manager;

import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author ：zzh
 * time ： 2021/5/21 13:32
 */
public class SocketManager implements ISocketManager {
    private final String TAG = SocketManager.class.getSimpleName();
    //socket服务初始化
    private ServerSocket mServerSocket;
    private SocketConnectThread socketConnectThread;
    private ReceiveMsgThread receiveMsgThread;
    private Socket mSocket;
    private final boolean isUseUsb = false;
    // 通过usb通信
    private int port = 36103;
    // 通过局域网
//    private final int port = 8800;

    public static final String sCharset = "utf-8";
    ISocketManager.Host host;

    public void setHost(Host host) {
        this.host = host;
    }

    @Override
    public void init() {
        try {
            if (!isUseUsb)
                port = 8800;
            if (mServerSocket == null)
                mServerSocket = new ServerSocket(port);
            socketConnectThread = getSocketConnectThread();
            receiveMsgThread = getReceiveMsgThread();
        } catch (Exception e) {
            Log.w(TAG, "new ServerSocket failed info=" + e.getMessage());
        }
    }

    private SocketConnectThread getSocketConnectThread() {
        if (socketConnectThread == null)
            socketConnectThread = new SocketConnectThread();
        return socketConnectThread;
    }

    private ReceiveMsgThread getReceiveMsgThread() {
        if (receiveMsgThread == null)
            receiveMsgThread = new ReceiveMsgThread();
        return receiveMsgThread;
    }

    @Override
    public void connect() {
        if (mSocket == null || !mSocket.isConnected()) {
            getSocketConnectThread().start();
        }
    }

    @Override
    public void disconnect() {
        if (mSocket != null && mSocket.isConnected()) {
            try {
                mSocket.close();
                mSocket = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (socketConnectThread != null) {
                socketConnectThread.interrupt();
                socketConnectThread = null;
            }
            if (receiveMsgThread != null) {
                receiveMsgThread.interrupt();
                receiveMsgThread = null;
            }
        }
    }
    // 计算发送数据评率
    private int availableCount = 0;
    private long availableStartTime;

	// 需要在单一线程中发送数据，防止数据错乱(特别是发送有序的大量数据时，可考虑使用队列方式逐条发送)。
    @Override
    public void sendData(byte[] data) {
        if (mSocket == null) {
            return;
        }
        if (data == null || data.length == 0) {
            return;
        }
        final byte[] finalData = data;
        data = null;
		byte[] msgBuffer;
		try {
			if (mSocket != null) {
				OutputStream mOutputStream = mSocket.getOutputStream();
				msgBuffer = finalData;
				mOutputStream.write(msgBuffer);

//                        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(mOutputStream));
//                        String send = new String(finalData);
//                        writer.write(send, 0, send.length());
//                        writer.flush();
				//preSendTime = System.currentTimeMillis();

				Log.d(TAG, "sendData byte[] finished, finalData=" + finalData.length
						+ ", finalData[finalData.length - 1]=" + finalData[finalData.length - 1] /*+ ", send str length=" + send.length()*/);
				if (availableCount == 0) {
					availableStartTime = System.currentTimeMillis();
				} else if (availableCount > 0) {
					long timeMs = System.currentTimeMillis() - availableStartTime;
					float f_frame_rate = (float) 1000 * (float) availableCount / (float) (timeMs);
					Log.d(TAG, "sendData avg rate:" + Float.toString(f_frame_rate));
				}
				availableCount++;

			}
		} catch (IOException e) {
			Log.e(TAG, "sendData string e:" + e.getMessage());
		} catch (Exception e2) {
			Log.e(TAG, "sendData string e2:" + e2.getMessage());
		}
    }

    @Override
    public void destroy() {
        disconnect();
        try {
            mServerSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        socketConnectThread = null;
        receiveMsgThread = null;
    }

    /**
     * 连接socket线程，启动socket
     */
    private class SocketConnectThread extends Thread {
        @Override
        public void run() {
            try {
                //实例化ServerSocket对象并设置端口号为8888
                if (mServerSocket == null) {
                    return;
                }
                Log.i(TAG, "InitSocketThread: 等待客户端的连接");
                //等待客户端的连接（阻塞）
                mSocket = mServerSocket.accept();
                // 最大可设成1048576
                mSocket.setSendBufferSize(1048576);
                Log.i(TAG, "InitSocketThread: 客户端已连接：" + mSocket.toString() + ", SendBufferSize=" + mSocket.getSendBufferSize());
                InetAddress inetAddress = mSocket.getInetAddress();
                String hostAddress = inetAddress.getHostAddress();
                Log.i(TAG, "InitSocketThread: hostAddress=" + hostAddress);

                // 通过usb通信 @{
                //只允许本地连接
                /*if (!"127.0.0.1".equals(hostAddress)) {
                    Log.i(TAG, "InitSocketThread: 服务器拒绝连接：" + mSocket.toString() + "；连接断开");
                    mSocket.close();
                }*/
                // @}

                if (host != null)
                    host.onConnectSuccess();

                // 开始接收数据的线程
                getReceiveMsgThread().start();

            } catch (IOException e) {
                if (mSocket != null) {
                    try {
                        mSocket.close();
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }
                }
                Log.e(TAG, "run: socket断开：" + e.getMessage());
            }
        }
    }

    private class ReceiveMsgThread extends Thread {
        @Override
        public void run() {
            try {
                if (mSocket != null) {
                    while (mSocket.isConnected()) {
                        InputStream inputStream = mSocket.getInputStream();
                        if (inputStream != null) {
                            byte[] buffer = new byte[1024];
                            int len = inputStream.read(buffer);
                            byte[] data = new byte[len];
                            System.arraycopy(buffer, 0, data, 0, len);
                            //String receiveMsg = new String(buffer, 0, len, charSet);
                            Log.d(TAG, "receiveMsg, len11=" + len + ", msg=" + new String(data, sCharset));
                            if (host != null)
                                host.onReceiveData(data);
                            //Log.d(TAG, "receiveMsg, len22=" + len + ", msg=" + new String(data, sCharset));
                        }
                    }
                }
            } catch (Exception e) {
                Log.e(TAG, "receive msg failed error=" + e.getMessage());
            }
        }
    }
}
